/*
 * Copyright (C) 2012 Jonathan St-Michel <jonathan@abiwebz.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.abiwebz.platform.util;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author stmicj
 */
public class ModuleLoader {
    
     /********* SINGLETON *****************************************************/
    protected static ModuleLoader singletonInstance = null;
    
    /**
     * Retourner une copie du ModuleLoader pour pouvoir aller chercher les
     * ressources ainsi que les classes des plugins.
     * 
     * @return Une copie du ModuleLoader
     */
    public static ModuleLoader getInstance(){
        return ModuleLoader.singletonInstance;
    }
    
    /**
     * Créer selon la technique du "singleton" l'instance de la classe 
     * ModuleLoader qui pourra être récupérée de n'importe où.
     * 
     * @return Une copie du ModuleLoader
     */
    public static ModuleLoader newInstance(File path){
        ModuleLoader.singletonInstance = new ModuleLoader(path);
        return ModuleLoader.getInstance();
    }
    
    //------------------------------------
    
    private ModuleClassLoader mcl;
    
    /**
     * Constructeur du ModuleLoader. Le path doit être donné pour initialiser 
     * le nouveau ClassLoader.
     * 
     * @param path Chemin d'accès des plugins
     */
    private ModuleLoader(File path) {
        this.mcl = new ModuleClassLoader(scanFolder(path), this.getClass().getClassLoader());
    }
    
    public final URL[] scanFolder(File folder) {
        File[] files = folder.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().toLowerCase().endsWith(".jar");
            }
        });

        URL[] urls = new URL[files.length];
        for (int i = 0; i < files.length; i++) {
            try {
                urls[i] = files[i].toURI().toURL();
            } catch (MalformedURLException ex) {
                Logger.getLogger(ModuleLoader.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return urls;
    }
    
    public Class<?> loadClass(String classname) throws ClassNotFoundException{
        return this.mcl.loadClass(classname);
    }
    
    public URL getResource(String name){
        return this.mcl.getResource(name);
    }
    
    public Enumeration<URL> getResources(String name) throws IOException{
        return this.mcl.getResources(name);
    }
    
    private class ModuleClassLoader extends URLClassLoader {

        public ModuleClassLoader(URL[] urls, ClassLoader cl) {
            super(urls, cl);
        }
        
        public void scanFolder(File folder) {
            File[] files = folder.listFiles(new FileFilter() {

                @Override
                public boolean accept(File pathname) {
                    return pathname.getName().endsWith(".jar");
                }
            });

            for (File module : files) {
                try {
                    this.addURL(module.toURI().toURL());
                } catch (MalformedURLException ex) {
                    Logger.getLogger(ModuleLoader.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        
    }
    
}
